

package yf.mall.service.impl;

import com.github.pagehelper.PageHelper;
import com.yf.annotation.LoginUserId;
import com.yf.response.RRException;
import lombok.experimental.var;
import org.springframework.transaction.annotation.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.excel.EasyExcel;
import yf.mall.common.Const;
import yf.mall.dao.AccountRecordDao;
import yf.mall.entity.*;
import yf.mall.enums.*;
import yf.mall.service.*;
import yf.mall.vo.AccountMyProfitVO;
import yf.mall.vo.AccountRecordVo;
import yf.mall.vo.down.CashApplyDown;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletResponse;
import java.util.stream.Collectors;

import yf.mall.dao.CashApplyDao;
import yf.mall.vo.CashApplyVo;
import com.yf.service.impl.BaseServiceImpl;

/**
 * 账户记录Service实现类
 *
 * @author hxf
 * @email 505860922@qq.com
 * @date Tue Sep 29 10:16:21 CST 2020
 */
@Service
public class CashApplyServiceImpl extends BaseServiceImpl<CashApplyEntity> implements CashApplyService {

    private CashApplyDao dao;

    @Autowired
    private UserService userService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private MyService myService;

    @Autowired
    public void setDao(CashApplyDao dao) {
        this.dao = dao;
        super.setBaseDao(dao);
    }

    @Autowired
    private NoticeService noticeService;
    @Autowired
    private AccountRecordDao accountRecordDao;

    @Override
    public List<CashApplyVo> findVo(CashApplyVo vo) {
        return dao.findVo(vo);
    }

    @Override
    public CashApplyVo getVo(Long id) {
        return dao.getVo(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveVo(CashApplyVo vo) {
        return dao.save(vo.getEntity());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateVo(CashApplyVo vo) {
        return dao.update(vo.getEntity());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCashApply(CashApplyVo vo) {
        CashApplyEntity cashApply = vo.getCashApply();
        CashApplyEntity cashApplyEntity = this.dao.get(cashApply.getId());
        if (cashApplyEntity.getStatus().equals(CashApplyStatusEnum.REFUSE.getIndex()) || cashApplyEntity.getStatus().equals(CashApplyStatusEnum.PASS.getIndex())) {
            throw new RRException("该申请已通过或已拒绝");
        }
        UserEntity userEntity = userService.get(cashApply.getUserId());
        cashApply.setPassTime(new Date());
        this.dao.update(cashApply);
        if (cashApply.getStatus().equals(CashApplyStatusEnum.PASS.getIndex())) {
            this.noticeService.sendApplyCashStatus(userEntity.getOpenId(), cashApply.getAmount().toString(), cashApply.getCrateTime(), cashApply.getPassTime(), "普通提现", "审核通过", "您的提现申请已通过,已转银行处理，具体到账时间以银行为准，请注意查收~~");
        } else if (cashApply.getStatus().equals(CashApplyStatusEnum.REFUSE.getIndex())) {
            this.accountService.transfer(Const.ADMIN_ID, cashApply.getUserId(), AccountTypeEnum.CASH.getIndex(), cashApply.getAmount(), "该申请没有通过审核,钱已退还到账,编号:" + cashApply.getAppNo());
            this.noticeService.sendApplyCashStatus(userEntity.getOpenId(), "", cashApply.getCrateTime(), new Date(), "普通提现", "审核失败", "您的提现申请未通过,编号:" + cashApply.getAppNo());
        }
    }


    @Override
    public void downLoad(HttpServletResponse response, List<CashApplyVo> list) {
        try {
            List<CashApplyDown> datas = list.stream().map(item -> new CashApplyDown(item)).collect(Collectors.toList());
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("测试", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), CashApplyDown.class).sheet("模板").doWrite(datas);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**内部方法**/


    /**
     * 外部方法实现
     **/


    /**
     *  获取个人可提现金额
     * @param userId
     * @return
     */
    @Override
    public Map<String,Object> getApplyMoney(Long userId,int page,int limit,Boolean flag){
        Map<String,Object> map = new HashMap<>();
        BigDecimal noCanApply = new BigDecimal(BigInteger.ZERO);
        BigDecimal canApply = new BigDecimal(BigInteger.ZERO);
        //店铺利润实收款
        BigDecimal shopTotal = retailsReward(userId, AccountRecordBusEnum.SHOP.getIndex());
        //个人提现
        AccountEntity account = this.accountService.findByUserIdAndType(userId, AccountTypeEnum.CASH.getIndex());
        if (flag){

            //分享有利代金券实收款
            BigDecimal agentTotal = retailsReward(userId, AccountRecordBusEnum.SHARE_REWARD.getIndex());
            //店铺管理利润实收款
            BigDecimal shopManageTotal = retailsReward(userId, AccountRecordBusEnum.SHOP_MANAGER_REWARD.getIndex());

            //已经提现的金额
            BigDecimal cash = this.dao.findByUserId(userId,CashApplyIdentifyEnum.ONE.getIndex());
            if (cash == null){
                cash = BigDecimal.ZERO;
            }

            //代金券记录
            PageHelper.startPage(page,limit);
            List<AccountRecordEntity> list = accountRecordDao.findCanApply(userId, AccountRecordTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(), AccountRecordBusEnum.SHARE_REWARD.getIndex(),AccountRecordBusEnum.SHOP_MANAGER_REWARD.getIndex());

            //店铺和个人的可提现总金额
            canApply = agentTotal.add(shopManageTotal).subtract(cash);
            //如果可提现的总金额要大于账户总额
            if (canApply.compareTo(account.getAmount()) > 0){
                //可提现的额度
                canApply = account.getAmount();
                //不可提现的额度
             //   noCanApply = canApply.subtract(cash);
            }else {
                //不可提现的额度
                noCanApply = account.getAmount().subtract(canApply);
            }
            map.put("canApply",canApply);
            //不可提现金额
            map.put("noCanApply",noCanApply);
            //代金券记录
            map.put("accounts",list);
        }else {
            //已经提现的金额
            BigDecimal cash = this.dao.findByUserId(userId,CashApplyIdentifyEnum.SHOP.getIndex());
            if (cash == null){
                cash = BigDecimal.ZERO;
            }
            if (shopTotal.subtract(cash).compareTo(account.getAmount()) > 0){
                shopTotal = account.getAmount();
            }else {
                shopTotal =shopTotal.subtract(cash);
            }

            map.put("shopTotal",shopTotal);
        }
        return map;
    }

    /**
     * Long
     * <p>
     * 提现申请
     *
     * @param userId
     * @param cashApplyEntity
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(Long userId, CashApplyEntity cashApplyEntity) {
        UserEntity userEntity = this.userService.get(userId);
        AccountEntity account = this.accountService.findByUserIdAndType(userId, AccountTypeEnum.CASH.getIndex());
        // 1-没有代金券
        if (account == null || account.getAmount().compareTo(BigDecimal.ZERO)<= 0) {
            throw new RRException("账户余额不足");
        }
//        2-提现规则  超过100才能提现
        if (account.getAmount().compareTo(BigDecimal.valueOf(100)) < 0) {
            throw new RRException("您的代金券没有达到提现额度");
        }
       // 3- 每个月10-15号才能提现 只有个人提现才10-15号
        if (cashApplyEntity.getIdentify()==CashApplyIdentifyEnum.ONE.getIndex()){
            Calendar c = Calendar.getInstance();
            int date = c.get(Calendar.DATE);
            if (date < 10 || date > 15){
                throw new RRException("每个月10-15号才能提现");
            }
        }

//        3-一个月只能提一次
        /*SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Long number = this.dao.findByTime(sdf.format(new Date()), userId);
        if (number != null && number > 0) {
            throw new RRException("您本月只能提一次，请下个月再提现");
        }*/

//        4-提现最大值不能超过代金券 且不能超过分享有利+店铺利润的奖金+已经提现的额度
        // 已经提现的金额
        BigDecimal cash = this.dao.findByUserId(userId,cashApplyEntity.getIdentify());
        if (cash == null){
            cash=BigDecimal.ZERO;
        }

        //5- 获取可提现的总额度
        //分享有利实收款
        BigDecimal retailsTotal = retailsReward(userId, AccountRecordBusEnum.SHARE_REWARD.getIndex());
        //店铺利润实收款
        BigDecimal shopTotal = retailsReward(userId, AccountRecordBusEnum.SHOP.getIndex());
        //店铺管理利润实收款
        BigDecimal shopManageTotal = retailsReward(userId, AccountRecordBusEnum.SHOP_MANAGER_REWARD.getIndex());

        //计算可提现的额度  分享有利+店铺利润+店铺管理利润+已经提现的额度
        BigDecimal total = BigDecimal.ZERO;
        if (cashApplyEntity.getIdentify().equals(CashApplyIdentifyEnum.ONE.getIndex())){
            //个人提现只计算分享有利和店铺管理的提现余额
            total = total.add(retailsTotal).add(shopManageTotal).subtract(cash);
        }else {
            //店铺提现只计算店铺费用
            total = total.add(shopTotal).subtract(cash);
        }

        //6-如果提现金额要大于可提现的金额或者提现金额要大于账户总额度 提示最多可提现多少
        if (cashApplyEntity.getAmount().compareTo(total) > 0 || cashApplyEntity.getAmount().compareTo(account.getAmount()) > 0) {
            if (total.compareTo(account.getAmount()) > 0) {
                throw new RRException("您最多可以提现" + account.getAmount()+"元");
            } else {
                throw new RRException("您最多可以提现" + total+"元");
            }
        }

        //7-如果账户余额小于等于0或者提现金额小于等于0或者账户余额减去提现金额小于0 则不可提现
        if (account.getAmount().compareTo(BigDecimal.ZERO) <= 0 || cashApplyEntity.getAmount().compareTo(BigDecimal.ZERO) <= 0 || account.getAmount().subtract(cashApplyEntity.getAmount()).compareTo(BigDecimal.ZERO) < 0) {
            throw new RRException("账户余额不足");
        }
        //8-生成提现记录
        cashApplyEntity.setStatus(CashApplyStatusEnum.AUDIT.getIndex());
        cashApplyEntity.setCrateTime(new Date());
        String no = createNO(userId);
        System.out.println(no);
        cashApplyEntity.setUserId(userId);
        cashApplyEntity.setAppNo(no);
        this.dao.save(cashApplyEntity);

        //9-扣除对应的提现额度
        accountService.transfer(userId, Const.ADMIN_ID, AccountTypeEnum.CASH.getIndex(), cashApplyEntity.getAmount(), userEntity.getName() + "申请提现了" + cashApplyEntity.getAmount() + "￥,编号:" + cashApplyEntity.getAppNo());
        //10-发送提现通知
        this.noticeService.sendApplyCash(userEntity.getOpenId(), cashApplyEntity.getAmount().toString(), cashApplyEntity.getCrateTime(), "商城提现", userEntity.getName() + "申请提现:" + cashApplyEntity.getAmount() + "元,编号:" + cashApplyEntity.getAppNo());
    }


    //分享有利
    private BigDecimal retailsReward(Long userId,Integer bus) {
        String time = "2020-6-15";

        //奖励
        List<AccountRecordEntity> accountReward = accountRecordDao.findByToUserIdAndBus(userId, bus, time);
        //追回
        List<AccountRecordEntity> accountBack = accountRecordDao.findByFromUserIdAndBus(userId, bus, time);

        //奖励
        BigDecimal retailsReward = new BigDecimal(0);
        //追回
        BigDecimal retailsBack = new BigDecimal(0);
        //奖励的
        if (null != accountReward && accountReward.size() > 0) {
            for (AccountRecordEntity recordEntity : accountReward) {
                if (null != recordEntity.getType()) {
                    //分享有利代金券
                    if (null != recordEntity.getAmount() && recordEntity.getStatus() == AccountRecordStatusEnum.DONE.getIndex()
                            && recordEntity.getType().equals(AccountTypeEnum.CASH.getIndex())) {
                        retailsReward = retailsReward.add(recordEntity.getAmount());
                    }
                }
            }
        }
        //退回的
        if (null != accountBack && accountBack.size() > 0) {
            for (AccountRecordEntity recordEntity : accountBack) {
                if (null != recordEntity.getType()) {
                    //分享有利代金券
                    if (null != recordEntity.getAmount() && recordEntity.getStatus() == AccountRecordStatusEnum.DONE.getIndex()
                            && recordEntity.getType().equals(AccountTypeEnum.CASH.getIndex())) {
                        if (recordEntity.getToUserId() == userId) {
                            continue;
                        }
                        retailsBack = retailsBack.add(recordEntity.getAmount());
                    }
                }
            }
        }
        return retailsReward.subtract(retailsBack);
    }

    //创建提现编号
    private String createNO(Long userId) {
        return System.currentTimeMillis() + "" + Math.round(Math.random() * 100) + "" + userId;
    }
}
